#ifndef __UDP_CLIENT_HPP__
#define __UDP_CLIENT_HPP__
#include "MyPthread/Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
using namespace LogMoudule;

const static int gsockfd = -1;
class UdpClient
{
private:


public:
    UdpClient()
        : _sockfd(gsockfd),_server(server_ip,server_port)
    {
    }
    ~UdpClient()
    {
    }
        // 1. 创建socket
    void InitClient()
    {
        // 1. 创建socket
        _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(LogLevel::ERROR) << "socket error";
            Die(SOCKET_ERR);
        }
        // // 1.1 server地址，设置server段属性
        // _server.sin_family = AF_INET;                             // 协议族
        // _server.sin_port = ::htons(server_port);                  // 端口号
        // _server.sin_addr.s_addr = ::inet_addr(server_ip.c_str()); // 地址
    }
    void Start()
    {
        // 2. clientdone
        while (true)
        {
            std::cout << "Please Enter# ";
            std::string message;
            std::getline(std::cin, message);

            for(auto e : message)
            {
                LOG(LogLevel::DEBUG)<<"message : "<<(int)e;
            }

            // client 不需要bind吗？socket <-> socket
            // client必须也要有自己的ip和端口！但是客户端，不需要自己显示的调用bind！！
            // 而是，客户端首次sendto消息的时候，由OS自动进行bind
            // 1. 如何理解client自动随机bind端口号？ 一个端口号，只能被一个进程bind
            // 2. 如何理解server要显示的bind？服务器的端口号，必须稳定！！必须是众所周知且不能改变轻易改变的!
            int n = ::sendto(_sockfd, message.c_str(), message.size(), 0, CONV(&_server), sizeof(_server));
            (void)n;

            LOG(LogLevel::DEBUG) << "send succeed:" << message;

            // 3. udpsocket是全双工的，但为什么需要temp接受回来的信息呢?
            // UDP 是无连接协议，通信双方不需要建立持久连接。peer结构体在客户端中通常用于指定初始发送目标
            struct sockaddr_in temp;
            socklen_t len = sizeof(temp);
            char buffer[1024];
            n = ::recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, CONV(&temp), &len);
            if (n > 0)
            {
                buffer[n] = 0;
                std::cout << buffer << std::endl;
            }
        }
    }

public:
private:
    int _sockfd;
    // struct sockaddr_in _client;
    InetAddr _server;
};

#endif